package com.bgybmi.sendtoken;

import java.util.Map;
import java.util.concurrent.Callable;

import com.jfinal.kit.HttpKit;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.qyweixin.sdk.api.AccessToken;
import com.jfinal.qyweixin.sdk.api.AccessTokenApi;
import com.jfinal.qyweixin.sdk.api.ApiConfig;
import com.jfinal.qyweixin.sdk.api.ApiConfigKit;
import com.jfinal.qyweixin.sdk.api.ApiResult;
import com.jfinal.qyweixin.sdk.api.SendMessageApi;
import com.jfinal.qyweixin.sdk.cache.IAccessTokenCache;
import com.jfinal.qyweixin.sdk.kit.ParaMap;
import com.jfinal.qyweixin.sdk.msg.send.QiYeTextMsg;
import com.jfinal.qyweixin.sdk.utils.HttpUtils;
import com.jfinal.qyweixin.sdk.utils.RetryUtils;

import sun.management.resources.agent;

public class SendTokenAgentIdApi extends SendMessageApi {
	
	private static final String tokenurl="https://qyapi.weixin.qq.com/cgi-bin/gettoken";
	
	private static final String sendurl = "https://qyapi.weixin.qq.com/cgi-bin/message/send";

	public static AccessToken getAccessToken(String agentId) {
		ApiConfig ac = ApiConfigKit.getApiConfig(agentId);
		AccessToken result = getAvailableAccessToken(ac);
		if (result != null) {
			return result;
		}
		return refreshAccessTokenIfNecessary(ac);
	}	

	private static AccessToken getAvailableAccessToken(ApiConfig ac) {
		// 利用 appId 与 accessToken 建立关联，支持多账户
		IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache();

		String accessTokenJson = accessTokenCache.get(ac.getAgentId());
		if (StrKit.notBlank(accessTokenJson)) {
			AccessToken result = new AccessToken(accessTokenJson);
			if (result != null && result.isAvailable()) {
				return result;
			}
		}
		return null;
	}

	/**
	 * synchronized 配合再次获取 token 并检测可用性，防止多线程重复刷新 token 值
	 */
	private static synchronized AccessToken refreshAccessTokenIfNecessary(ApiConfig ac) {
		AccessToken result = getAvailableAccessToken(ac);
		if (result != null) {
			return result;
		}
		return refreshAccessToken(ac);
	}

	/**
	 * 无条件强制更新 access token 值，不再对 cache 中的 token 进行判断
	 * 
	 * @param ac
	 *            ApiConfig
	 * @return AccessToken
	 */
	public static AccessToken refreshAccessToken(ApiConfig ac) {
		String corpid = ac.getCorpId();
		String corpsecret = ac.getCorpSecret();
		final Map<String, String> queryParas = ParaMap.create("corpid", corpid).put("corpsecret", corpsecret).getData();
		
		//这里应该 Accesstoken更好
		// 最多三次请求
		AccessToken result = RetryUtils.retryOnException(3, new Callable<AccessToken>() {

			@Override
			public AccessToken call() throws Exception {
				String json = HttpUtils.get(tokenurl, queryParas);
				return new AccessToken(json);
			}
		});

		// 三次请求如果仍然返回了不可用的 access token 仍然 put 进去，便于上层通过 AccessToken 中的属性判断底层的情况
		if (null != result) {
			// 利用 appId 与 accessToken 建立关联，支持多账户
			IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache();
			accessTokenCache.set(ac.getAgentId(), result.getCacheJson());
		}
		return result;
	}

	public static ApiResult sendTextMsg(QiYeTextMsg text,String agentId) {		
		String jsonStr = JsonKit.toJson(text);
		return sendMessage(jsonStr,agentId);
	}
	
	public static ApiResult sendMessage(String jsonStr,String agentId) {
		ParaMap pm = ParaMap.create("access_token", getAccessToken(agentId).getAccessToken());// 得到了基本的																				// 接口
		return new ApiResult(HttpKit.post(sendurl, pm.getData(), jsonStr));// 可以通过本链接获取到Json
																		// 信息的封装
	}

}
